/*
 * Copyright 2024 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.pajamas.example.client.starter.integration.module.context;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;

import org.apache.commons.lang3.StringUtils;
import org.pajamas.daydream.treeFlatFormat.json.AbstractJsonTreeFlatFormatter;
import org.pajamas.daydream.treeFlatFormat.json.JacksonJsonTreeFlatFormatter;
import org.pajamas.daydream.wrapper.commons.jackson.CommonsWrapperModule;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.DefaultPropertySourceFactory;
import org.springframework.core.io.support.EncodedResource;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;

/**
 * @author william
 * @since 2024/1/6
 */

public class JsonPropertySourceFactory extends DefaultPropertySourceFactory {
    private static final transient ObjectMapper OBJECT_MAPPER;
    private static final transient AbstractJsonTreeFlatFormatter JSON_TREE_FLAT_FORMATTER;

    static {
        OBJECT_MAPPER = new ObjectMapper()
                .enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)
                .registerModule(new Jdk8Module())
                .registerModule(new CommonsWrapperModule());
        JSON_TREE_FLAT_FORMATTER = new JacksonJsonTreeFlatFormatter(OBJECT_MAPPER);
    }

    private static MapPropertySource parsePropertySource(String propertySourceName, EncodedResource resource) throws IOException {
        InputStream inputStream = resource.getInputStream();
        Map<String, Object> flatMap = JSON_TREE_FLAT_FORMATTER.format(inputStream);
        return new MapPropertySource(propertySourceName, flatMap);
    }

    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        String sourceName = name != null ? name : resource.getResource().getFilename();
        if (StringUtils.isBlank(sourceName)) {
            throw new IOException("createPropertySource.sourceName can not be blank");
        }

        if (!resource.getResource().exists()) {
            return new PropertiesPropertySource(sourceName, new Properties());
        } else if (sourceName.endsWith(".json")) {
            return parsePropertySource(name, resource);
        } else {
            return super.createPropertySource(name, resource);
        }
    }
}
